/*
 * Copyright (c) 2003-2010, Live Media Pty. Ltd.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice, this list of
 *     conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice, this list of
 *     conditions and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *  3. Neither the name of Live Media nor the names of its contributors may be used to endorse
 *     or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <string.h>

#include "contiki.h"
#include "contiki-net.h"

#include "dev/leds.h"


#include "common.h"
#include "buffers.h"
#include "type-protocol.h"

#define PRINTF printf

#define UDP_DATA_LEN 120
#define UDP_HDR ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])

extern char send_buffer[];
extern int send_pos;

#ifdef DEBUG

void printData( char * data, int len )
{
	int x;
	
	printf("DATA RECEIVED %i\n", len);
	for( x=0; x<len; x++ )
	{
		printf("%x,", data[x] );
	}
	printf("\n");
}

#endif

static struct uip_udp_conn *udpconn;
static uint8_t udpdata[UDP_DATA_LEN] = "rx=";

static void udphandler(process_event_t ev, process_data_t data)
{
    int rc;
    uint16_t msgType;

    if (uip_newdata())
    {
        /* Set the last byte of the received data as 0 in order to print it. */
        int len = uip_datalen();
        ((char *)uip_appdata)[len] = 0;

	/* Reset the receive buffer & send buffer */
	read_reset( uip_appdata );
	send_clear();

        /* print the receiver IP address and port */
        TRACE("Received from %u.%u.%u.%u:%u\n", uip_ipaddr_to_quad(&UDP_HDR->srcipaddr), HTONS(UDP_HDR->srcport));

        
        msgType = read_u8();
/* 
        size = read_u32();
        if ( size > BUFSIZE ) 
	{
           TRACE("SIZE LARGER THAN BUFSIZE\n" );
           return;
        }
*/     
	rc = processTypeMessage( msgType, 0 );
	if ( rc == PROCESS_OK )
	{
           /* Copy the information about the sender to the udpconn in order to reply */
           uip_ipaddr_copy(&udpconn->ripaddr , &UDP_HDR->srcipaddr); // ip address
           udpconn->rport = UDP_HDR->srcport; // UDP port
        
           /* Send the reply datagram */
           TRACE("sending response - length %i\n", send_pos);
	   uip_udp_packet_send(udpconn, send_buffer,send_pos );
	}
   
        /* Prepare the response datagram in a local buffer */
        memcpy(udpdata, "rx=", 3);
        memcpy(udpdata+3, uip_appdata, len);
        
        
        /* Restore the udpconn to previous setting in order to receive other packets */
        uip_ipaddr_copy(&udpconn->ripaddr , &uip_all_zeroes_addr);
        udpconn->rport = 0;
    }
}

/*---------------------------------------------------------------------------*/
/*
 * We declare the process.
 */
PROCESS(example_udp_server_process, "Example UDP server");
AUTOSTART_PROCESSES(&example_udp_server_process);
/*---------------------------------------------------------------------------*/
/*
 * The definition of the process.
 */
PROCESS_THREAD(example_udp_server_process, ev, data)
{
    
    PROCESS_BEGIN();
    printf("UDP Echo Server test\n");
    
    /* Create a UDP 'connection' with IP 0.0.0.0 and port 0 as remote host.
     * This means the stack will accepts UDP datagrams from any node. */
    udpconn = udp_new(NULL, HTONS(0), NULL);
    
    /* Bind the UDP 'connection' to the port 50000. That's the port we're listening on. */
    udp_bind(udpconn, HTONS(50000));

    TRACE("listening on UDP port %u\n", HTONS(udpconn->lport));
    
    while(1) {
        /* Wait until we have an event caused by tcpip interaction */
        PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event);

	TRACE("got tcpip_event");
        /* Handle it */
        udphandler(ev, data);
    }
    
    PROCESS_END();
}
/*---------------------------------------------------------------------------*/
